package com.axeiya.cheddargetter;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.xpath.XPath;

public class Subscription {
	
	public static enum FormatType{
		CREATEFREE,
		CREATE,
		UPDATE,
		UPDATEFREE;
	}


	/**
	 * Your code for the subscribed pricing plan
	 * REQUIRED
	 */
	private PricingPlan plan;
	
	/**
	 * YYYY-MM-DD - Date on which you would like the customers first invoice to be billable. This option overrides the pricing plan default. Must either be today's date (run invoice immediately) or a future date.
	 */
	private Date initialBillDate;
	
	/**
	 * Numbers only -- a valid credit/debit card number
	 * REQUIRED UNLESS PLAN IS FREE
	 */
	private long ccNumber; 
	
	/**
	 * MM/YYYY - the expiration date for the credit card
	 * REQUIRED UNLESS PLAN IS FREE
	 */
	private Date ccExpirationDate;
	
	/**
	 * 3-4 digits - The Card Verification Value (CCV).
	 * IF PLAN IS FREE, NOT REQUIRED.
	 * ELSE IF PREFERENCES SAYS SO, REQUIRED.
	 */
	private int ccCardCode;
	
	/**
	 * Limited to 20 characters
	 * REQUIRED UNLESS PLAN IS FREE
	 */
	private String ccFirstName;
	
	/**
	 * Limited to 20 characters
	 * REQUIRED UNLESS PLAN IS FREE
	 */
	private String ccLastName;
	
	/**
	 * Limited to 50 characters
	 */
	private String ccCompany;
	
	/**
	 * Limited to 60 characters
	 */
	private String ccCountry;
	
	/**
	 * Limited to 60 characters
	 */
	private String ccAddress;

	/**
	 * Limited to 40 characters
	 */
	private String ccCity;
	
	/**
	 * Limited to 40 characters
	 */
	private String ccState;
	
	/**
	 * Limited to 50 characters
	 * IF PLAN IS FREE, NOT REQUIRED.
	 * ELSE IF PREFERENCES SAYS SO, REQUIRED.
	 */
	private String ccZip;
	
	private boolean freePlan;
	
	
	
	/**
	 * READ ONLY PARAMETERS
	 */
	
	private String gatewayToken;
	private String ccLastFour;
	private Date createdDatetime;
	private Date canceledDatetime;
	private ArrayList<SubscriptionItem> subscriptionsItems;
	private ArrayList<Invoice> invoices;
	
	
	/**
	 * FREE PLAN SUBSCRIPTION
	 */
	public Subscription(PricingPlan planCode){
		this.plan = planCode;
		freePlan = true;
	}
	
	/**
	 * DEFAULT NOT FREE PLAN SUBSCRIPTION WITH DATE
	 */
	public Subscription(PricingPlan planCode, long ccNumber, Date ccExpirationDate, String ccFirstName, String ccLastName){
		this.plan = planCode;
		this.ccNumber = ccNumber;
		this.ccExpirationDate = ccExpirationDate;
		this.ccFirstName = ccFirstName;
		this.ccLastName = ccLastName;
		freePlan = false;
	}
	
	/**
	 * DEFAULT NOT FREE PLAN SUBSCRIPTION WITH STRINGS
	 */
	public Subscription(PricingPlan planCode, long ccNumber, String ccExpirationDate, String ccFirstName, String ccLastName){
		this.plan = planCode;
		this.ccNumber = ccNumber;
		DateFormat formatter = new SimpleDateFormat("MM/yyyy");
		try {
			this.ccExpirationDate = formatter.parse(ccExpirationDate);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		this.ccFirstName = ccFirstName;
		this.ccLastName = ccLastName;
		freePlan = false;
	}
	
	/**
	 * NOT FREE PLAN WITH CCCARDCODE WITH DATE
	 */
	public Subscription(PricingPlan planCode, long ccNumber, int ccCardCode, Date ccExpirationDate, String ccFirstName, String ccLastName){
		this.plan = planCode;
		this.ccNumber = ccNumber;
		this.ccCardCode = ccCardCode;
		this.ccExpirationDate = ccExpirationDate;
		this.ccFirstName = ccFirstName;
		this.ccLastName = ccLastName;
		freePlan = false;
	}
	
	/**
	 * NOT FREE PLAN WITH CCCARDCODE WITH STRINGS
	 */
	public Subscription(PricingPlan planCode, long ccNumber, int ccCardCode, String ccExpirationDate, String ccFirstName, String ccLastName){
		this.plan = planCode;
		this.ccNumber = ccNumber;
		this.ccCardCode = ccCardCode;
		DateFormat formatter = new SimpleDateFormat("MM/yyyy");
		try {
			this.ccExpirationDate = formatter.parse(ccExpirationDate);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		this.ccFirstName = ccFirstName;
		this.ccLastName = ccLastName;
		freePlan = false;
	}
	

	
	/**
	 * NOT FREE PLAN WITH CCZIP WITH DATES
	 */
	public Subscription(PricingPlan planCode, long ccNumber, Date ccExpirationDate, String ccFirstName, String ccLastName, String ccZip){
		this.plan = planCode;
		this.ccNumber = ccNumber;
		this.ccExpirationDate = ccExpirationDate;
		this.ccFirstName = ccFirstName;
		this.ccLastName = ccLastName;
		this.ccZip = ccZip;
		freePlan = false;
	}
	
	/**
	 * NOT FREE PLAN WITH CCZIP WITH STRINGS
	 */
	public Subscription(PricingPlan planCode, long ccNumber, String ccExpirationDate, String ccFirstName, String ccLastName, String ccZip){
		this.plan = planCode;
		this.ccNumber = ccNumber;
		DateFormat formatter = new SimpleDateFormat("MM/yyyy");
		try {
			this.ccExpirationDate = formatter.parse(ccExpirationDate);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		this.ccFirstName = ccFirstName;
		this.ccLastName = ccLastName;
		this.ccZip = ccZip;
		freePlan = false;
	}

	
	/**
	 * NOT FREE PLAN WITH CCCARDCODE & CCZIP WITH DATE
	 */
	public Subscription(PricingPlan planCode, long ccNumber, int ccCardCode, Date ccExpirationDate, String ccFirstName, String ccLastName, String ccZip){
		this.plan = planCode;
		this.ccNumber = ccNumber;
		this.ccCardCode = ccCardCode;
		this.ccExpirationDate = ccExpirationDate;
		this.ccFirstName = ccFirstName;
		this.ccLastName = ccLastName;
		this.ccZip = ccZip;
		freePlan = false;
	}
	
	/**
	 * NOT FREE PLAN WITH CCCARDCODE & CCZIP WITH STRINGS
	 */
	public Subscription(PricingPlan planCode, long ccNumber, int ccCardCode, String ccExpirationDate, String ccFirstName, String ccLastName, String ccZip){
		this.plan = planCode;
		this.ccNumber = ccNumber;
		this.ccCardCode = ccCardCode;
		DateFormat formatter = new SimpleDateFormat("MM/yyyy");
		try {
			this.ccExpirationDate = formatter.parse(ccExpirationDate);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		this.ccFirstName = ccFirstName;
		this.ccLastName = ccLastName;
		this.ccZip = ccZip;
		freePlan = false;
	}
	
	/**
	 * READ CONSTRUCTOR
	 */
	public Subscription(Date ccExpirationDate,String ccFirstName, String ccLastName, String ccCompany,
			String ccCountry, String ccAddress, String ccCity, String ccState, String ccZip,
			String gatewayToken, String ccLastFour, Date createdDatetime, Date canceledDatetime,
			ArrayList<SubscriptionItem> subscriptionsItems, ArrayList<Invoice> invoices) {
		super();
		this.ccExpirationDate = ccExpirationDate;
		this.ccFirstName = ccFirstName;
		this.ccLastName = ccLastName;
		this.ccCompany = ccCompany;
		this.ccCountry = ccCountry;
		this.ccAddress = ccAddress;
		this.ccCity = ccCity;
		this.ccState = ccState;
		this.ccZip = ccZip;
		this.gatewayToken = gatewayToken;
		this.ccLastFour = ccLastFour;
		this.createdDatetime = createdDatetime;
		this.canceledDatetime = canceledDatetime;
		this.subscriptionsItems = subscriptionsItems;
		this.invoices = invoices;
	}

	
	public static Subscription parseSubscription(Element subscription){
	
		String gatewayToken = subscription.getChildText("gatewayToken");
		String ccFirstName = subscription.getChildText("ccFirstName");
		String ccLastName = subscription.getChildText("ccLastName");
		String ccCountry = subscription.getChildText("ccCountry");
		String ccAddress = subscription.getChildText("ccAddress");
		String ccCompany = subscription.getChildText("ccCompany");
		String ccCity = subscription.getChildText("ccCity");
		String ccState = subscription.getChildText("ccState");
		String ccZip = subscription.getChildText("ccZip");
		String ccType = subscription.getChildText("ccType");
		String ccLastFour = subscription.getChildText("ccLastFour");
		
		DateFormat formatter = new SimpleDateFormat();
		Date ccExpirationDate = null;
		try {
			ccExpirationDate = formatter.parse(subscription.getChildText("ccExpirationDate"));
		} catch (ParseException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		Date canceledDatetime = CGTools.parseDateTime(subscription.getChildText("canceledDatetime"));
		Date createdDatetime = CGTools.parseDateTime(subscription.getChildText("createdDatetime"));
	
		ArrayList<SubscriptionItem> subscriptionItems = new ArrayList<SubscriptionItem>();
		ArrayList<Invoice> invoices = new ArrayList<Invoice>();
		try {
		List<Element> itemsElement = XPath.selectNodes(subscription, "items/item");
		for (Element itemElement : itemsElement) {
			subscriptionItems.add(SubscriptionItem.parseSubscriptionItem(itemElement));
		}
	
		List<Element> invoicesElement = XPath.selectNodes(subscription, "invoices/invoice");
		for (Element invoiceElement : invoicesElement) {
			invoices.add(Invoice.parseInvoice(invoiceElement));
		}
		} catch (JDOMException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return new Subscription(ccExpirationDate, ccFirstName, ccLastName, ccCompany, ccCountry, ccAddress, ccCity, ccState, ccZip, gatewayToken, ccLastFour, createdDatetime, canceledDatetime, subscriptionItems, invoices);
		
	}
	
	public static HashMap<String, String> formatSubscription(Subscription subscription, FormatType formatType){
		HashMap<String, String> parameters = new HashMap<String, String>();
		if(formatType == FormatType.CREATE || formatType == FormatType.CREATEFREE){
			if(subscription.getInitialBillDate() != null){
				DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
				parameters.put("initialBillDate", formatter.format(subscription.getInitialBillDate()));
			}

		}
		
		if(subscription.getPlan()!= null && subscription.getPlan().getCode() != null && !subscription.getPlan().getCode().isEmpty()){
			parameters.put("planCode", subscription.getPlan().getCode());
		}else{
			//TODO: throw exception
		}
		
		if(subscription.getCcNumber() > 0L ){
			parameters.put("ccNumber", String.valueOf(subscription.getCcNumber()));
		}else if(formatType != FormatType.CREATEFREE && formatType != FormatType.UPDATEFREE){
			//TODO: throw exception
		}
		
		if(subscription.getCcExpirationDate() != null){
			DateFormat formatter = new SimpleDateFormat("MM/yyyy");
			parameters.put("ccExpiration", formatter.format(subscription.getCcExpirationDate()));
		}else if(formatType != FormatType.CREATEFREE && formatType != FormatType.UPDATEFREE){
			//TODO: throw exception
		}
		
		if(subscription.getCcCardCode()>0){
			parameters.put("ccCardCode", String.valueOf(subscription.getCcCardCode()));
		}else if(formatType != FormatType.CREATEFREE && formatType != FormatType.UPDATEFREE){
			//TODO: throw exception
		}
		
		if(subscription.getCcFirstName() != null && !subscription.getCcFirstName().isEmpty()){
			parameters.put("ccFirstName", subscription.getCcFirstName());
		}else if(formatType != FormatType.CREATEFREE && formatType != FormatType.UPDATEFREE){
			//TODO: throw exception
		}
		
		if(subscription.getCcLastName() != null && !subscription.getCcLastName().isEmpty()){
			parameters.put("ccLastName", subscription.getCcLastName());
		}else if(formatType != FormatType.CREATEFREE && formatType != FormatType.UPDATEFREE){
			//TODO: throw exception
		}
		

		if(subscription.getCcZip() != null && !subscription.getCcZip().isEmpty()){
			parameters.put("ccZip", subscription.getCcZip());
		}else if(formatType != FormatType.CREATEFREE && formatType != FormatType.UPDATEFREE){
			//TODO: throw exception
		}
		
		if(subscription.getCcCompany() != null && !subscription.getCcCompany().isEmpty()){
			parameters.put("ccCompany", subscription.getCcCompany());
		}
		
		if(subscription.getCcCountry() != null && !subscription.getCcCountry().isEmpty()){
			parameters.put("ccCountry", subscription.getCcCountry());
		}
		if(subscription.getCcAddress() != null && !subscription.getCcAddress().isEmpty()){
			parameters.put("ccAddress", subscription.getCcAddress());
		}
		if(subscription.getCcCity() != null && !subscription.getCcCity().isEmpty()){
			parameters.put("ccCity", subscription.getCcCity());
		}
		if(subscription.getCcState() != null && !subscription.getCcState().isEmpty()){
			parameters.put("ccState", subscription.getCcState());
		}

		if(formatType == FormatType.UPDATE || formatType == FormatType.UPDATEFREE){
			//TODO:changeBillDate
		}
		
		return parameters;
	}
	
	
	public PricingPlan getPlan() {
		return plan;
	}

	public void setPlan(PricingPlan planCode) {
		this.plan = planCode;
	}

	public Date getInitialBillDate() {
		return initialBillDate;
	}

	public void setInitialBillDate(Date initialBillDate) {
		this.initialBillDate = initialBillDate;
	}

	public long getCcNumber() {
		return ccNumber;
	}

	public void setCcNumber(long ccNumber) {
		this.ccNumber = ccNumber;
	}

	public Date getCcExpirationDate() {
		return ccExpirationDate;
	}

	public void setCcExpirationDate(Date ccExpirationDate) {
		this.ccExpirationDate = ccExpirationDate;
	}

	public int getCcCardCode() {
		return ccCardCode;
	}

	public void setCcCardCode(int ccCardCode) {
		this.ccCardCode = ccCardCode;
	}

	public String getCcFirstName() {
		return ccFirstName;
	}

	public void setCcFirstName(String ccFirstName) {
		this.ccFirstName = ccFirstName;
	}

	public String getCcLastName() {
		return ccLastName;
	}

	public void setCcLastName(String ccLastName) {
		this.ccLastName = ccLastName;
	}

	public String getCcCompany() {
		return ccCompany;
	}

	public void setCcCompany(String ccCompany) {
		this.ccCompany = ccCompany;
	}

	public String getCcCountry() {
		return ccCountry;
	}

	public void setCcCountry(String ccCountry) {
		this.ccCountry = ccCountry;
	}

	public String getCcAddress() {
		return ccAddress;
	}

	public void setCcAddress(String ccAddress) {
		this.ccAddress = ccAddress;
	}

	public String getCcCity() {
		return ccCity;
	}

	public void setCcCity(String ccCity) {
		this.ccCity = ccCity;
	}

	public String getCcState() {
		return ccState;
	}

	public void setCcState(String ccState) {
		this.ccState = ccState;
	}

	public String getCcZip() {
		return ccZip;
	}

	public void setCcZip(String ccZip) {
		this.ccZip = ccZip;
	}

	public String getGatewayToken() {
		return gatewayToken;
	}

	public void setGatewayToken(String gatewayToken) {
		this.gatewayToken = gatewayToken;
	}

	public String getCcLastFour() {
		return ccLastFour;
	}

	public void setCcLastFour(String ccLastFour) {
		this.ccLastFour = ccLastFour;
	}

	public Date getCreatedDatetime() {
		return createdDatetime;
	}

	public void setCreatedDatetime(Date createdDatetime) {
		this.createdDatetime = createdDatetime;
	}

	public Date getCanceledDatetime() {
		return canceledDatetime;
	}

	public void setCanceledDatetime(Date canceledDatetime) {
		this.canceledDatetime = canceledDatetime;
	}

	public ArrayList<SubscriptionItem> getSubscriptionsItems() {
		return subscriptionsItems;
	}

	public void setSubscriptionsItems(ArrayList<SubscriptionItem> subscriptionsItems) {
		this.subscriptionsItems = subscriptionsItems;
	}

	public ArrayList<Invoice> getInvoices() {
		return invoices;
	}

	public void setInvoices(ArrayList<Invoice> invoices) {
		this.invoices = invoices;
	}

	public boolean isFreePlan() {
		return freePlan;
	}

	public void setFreePlan(boolean freePlan) {
		this.freePlan = freePlan;
	}
	
	
	
	
}
